﻿//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Microsoft Public License.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace DSPTest
{
    using System;
    using System.Collections;
    using System.Data.Services;
    using DataServiceProvider;

    public class Quantity
    {
        public double Value { get; set; }
        public string Units { get; set; }
    }

    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public double Price { get; set; }
        public DateTime ReleaseDate { get; set; }
        public DateTime? DiscontinueDate { get; set; }
        public int Rating { get; set; }
        public Quantity Quantity { get; set; }
    }

    public class ClientProduct
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        // The client product must not have the "Price" property since it's not visible to the user (it's not declared)
        public DateTime ReleaseDate { get; set; }
        public DateTime? DiscontinueDate { get; set; }
        public int Rating { get; set; }
        public Quantity Quantity { get; set; }
    }

    public class ProductsService : DSPDataService<DSPContext>
    {
        private static DSPContext context;
        private static DSPMetadata metadata;

        static ProductsService()
        {
            metadata = new DSPMetadata("ProductsContext", "DSPTest");

            var quantityType = metadata.AddComplexType(typeof(Quantity));
            metadata.AddPrimitiveProperty(quantityType, "Value");
            metadata.AddPrimitiveProperty(quantityType, "Units");

            var productType = metadata.AddEntityType(typeof(Product));
            metadata.AddKeyProperty(productType, "ID");
            metadata.AddPrimitiveProperty(productType, "Name");
            metadata.AddPrimitiveProperty(productType, "Description");
            metadata.AddPrimitiveProperty(productType, "ReleaseDate");
            metadata.AddPrimitiveProperty(productType, "DiscontinueDate");
            metadata.AddPrimitiveProperty(productType, "Rating");
            metadata.AddComplexProperty(productType, "Quantity", quantityType);

            metadata.AddResourceSet("Products", productType);

            context = CreateDataContext();
        }

        public static void ResetDataContext()
        {
            context = CreateDataContext();
        }

        public static IDisposable RestoreDataContext()
        {
            return new RestoreDataContextDisposable();
        }

        private class RestoreDataContextDisposable : IDisposable
        {
            #region IDisposable Members

            public void Dispose()
            {
                ProductsService.ResetDataContext();
            }

            #endregion
        }

        private static DSPContext CreateDataContext()
        {
            context = new DSPContext();
            IList products = context.GetResourceSetEntities("Products");
            products.Add(new Product()
            {
                ID = 0,
                Name = "Bread",
                Description = "Whole grain bread",
                Price = 3.5,
                ReleaseDate = new DateTime(1992, 1, 1),
                DiscontinueDate = null,
                Rating = 4,
                Quantity = new Quantity()
                {
                    Value = 12,
                    Units = "pieces"
                }
            });

            products.Add(new Product()
            {
                ID = 1,
                Name = "Milk",
                Description = "Low fat milk",
                Price = 2.4,
                ReleaseDate = new DateTime(1995, 10, 21),
                DiscontinueDate = null,
                Rating = 3,
                Quantity = new Quantity()
                {
                    Value = 4,
                    Units = "liters"
                }
            });

            products.Add(new Product()
            {
                ID = 2,
                Name = "Wine",
                Description = "Red wine, year 2003",
                Price = 19.9,
                ReleaseDate = new DateTime(2003, 11, 24),
                DiscontinueDate = new DateTime(2008, 3, 1),
                Rating = 5,
                Quantity = new Quantity()
                {
                    Value = 7,
                    Units = "bottles"
                }
            });

            return context;
        }

        protected override DSPContext CreateDataSource()
        {
            return context;
        }

        protected override DSPMetadata CreateDSPMetadata()
        {
            return metadata;
        }

        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = System.Data.Services.Common.DataServiceProtocolVersion.V2;
            config.DataServiceBehavior.AcceptCountRequests = true;
            config.DataServiceBehavior.AcceptProjectionRequests = true;
            config.UseVerboseErrors = true;
        }
    }
}
